package biz

import (
	"beetle/internal/model"
	"beetle/internal/pkg/constant"
	"encoding/json"
	"errors"
	"gorm.io/gorm"
)

type RedisRecordService interface {
	Save(model *model.RedisRecord) error
	Update(model *model.RedisRecord) error
	Remove(id int) error
	Find(id int) (*model.RedisRecord, error)
	Page(model *model.RedisRecord, pager model.Pager) *model.Page
}

type RedisRecordRepo interface {
	Save(model *model.RedisRecord) bool
	Update(model *model.RedisRecord) bool
	Remove(id int) bool
	Count(model *model.RedisRecord) int
	Find(id int) *model.RedisRecord
	Page(model *model.RedisRecord, pager model.Pager) []*model.RedisRecord
}

type redisRecordService struct {
	repo RedisRecordRepo
}

func (srv *redisRecordService) Save(record *model.RedisRecord) error {

	if record.Name == "" {
		return errors.New("参数名称不能为空")
	}

	if record.RequestHeader != nil {
		header, err := json.Marshal(record.RequestHeader)
		if err != nil {
			return err
		}
		record.Header = string(header)
	}

	success := srv.repo.Save(record)

	if success {
		return nil
	}
	return errors.New("保存失败")
}

func (srv *redisRecordService) Update(record *model.RedisRecord) error {

	if record.ID == 0 {
		return errors.New("参数错误")
	}

	if record.RequestHeader != nil {
		header, err := json.Marshal(record.RequestHeader)
		if err != nil {
			return err
		}
		record.Header = string(header)
	}

	success := srv.repo.Update(record)
	if success {
		return nil
	}
	return errors.New("更新失败")
}

func (srv *redisRecordService) Remove(id int) error {

	if id == 0 {
		return errors.New("ID不能为空")
	}

	success := srv.repo.Remove(id)

	if success {
		return nil
	}

	return errors.New("删除失败")
}

func (srv *redisRecordService) Find(id int) (*model.RedisRecord, error) {

	if id == 0 {
		return nil, errors.New("ID不能为空")
	}

	record := srv.repo.Find(id)

	if record == nil {
		return nil, errors.New("未找到有效的配置信息")
	}
	if record.Header != "" {
		err := json.Unmarshal([]byte(record.Header), &record.RequestHeader)
		if err != nil {
			return nil, err
		}
	}

	return record, nil
}

func (srv *redisRecordService) Page(record *model.RedisRecord, pager model.Pager) *model.Page {

	count := srv.repo.Count(record)

	records := srv.repo.Page(record, pager)
	if len(records) != 0 {
		for i := range records {
			if records[i].Header != "" {
				err := json.Unmarshal([]byte(records[i].Header), &records[i].RequestHeader)
				if err != nil {
					// todo log
				}
			}

		}
	}

	page := &model.Page{
		Total: count,
		List:  records,
	}

	return page
}

func NewRedisRecordService(repo RedisRecordRepo) *redisRecordService {
	return &redisRecordService{repo}
}

type redisRecordRepo struct {
	db *gorm.DB
}

func (repo *redisRecordRepo) Save(record *model.RedisRecord) bool {
	result := repo.db.Create(record)
	if result.Error != nil {
		return false
	}
	return true
}

func (repo *redisRecordRepo) Update(record *model.RedisRecord) bool {
	result := repo.db.Updates(record)
	if result.Error != nil {
		return false
	}
	return true
}

func (repo *redisRecordRepo) Remove(id int) bool {
	result := repo.db.Model(&model.RedisRecord{ID: id}).Update("DEL_FLAG", constant.DELETE)
	if result.Error != nil {
		return false
	}
	return true
}

func (repo *redisRecordRepo) Find(id int) *model.RedisRecord {
	var record model.RedisRecord
	result := repo.db.Where("DEL_FLAG= ? AND ID = ? ", constant.UNDELETE, id).First(&record)
	if result.Error != nil {
		return nil
	}
	return &record
}

func (repo *redisRecordRepo) Count(record *model.RedisRecord) int {
	var count int64
	tx := repo.pageCond(record)
	tx.Count(&count)
	return int(count)
}

func (repo *redisRecordRepo) Page(record *model.RedisRecord, pager model.Pager) []*model.RedisRecord {

	var records []*model.RedisRecord

	if pager.PageSize == 0 {
		pager.PageSize = 20
	}

	tx := repo.pageCond(record)

	result := tx.Offset((pager.PageNum - 1) * pager.PageSize).Limit(pager.PageSize).Find(&records)
	if result.Error != nil {
		return nil
	}
	return records
}

func (repo *redisRecordRepo) pageCond(record *model.RedisRecord) *gorm.DB {
	tx := repo.db.Model(&model.RedisRecord{}).Where("DEL_FLAG = ? ", constant.UNDELETE)

	if record.Name != "" {
		tx.Where("KEY LIKE ? ", "%"+record.Name+"%")
	}

	if record.Scope != "" {
		tx.Where("SCOPE LIKE ? ", "%"+record.Scope+"%")
	}
	return tx
}

func NewRedisRecordRepo(db *gorm.DB) *redisRecordRepo {
	return &redisRecordRepo{db}
}
